package com.fufan.mtsaas.modules.newtech.xjstech.service.impl;

import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fufan.mtsaas.config.RedissonCommand;
import com.fufan.mtsaas.constant.DefaultConstant;
import com.fufan.mtsaas.constant.RedisKeyConstant;
import com.fufan.mtsaas.modules.base.log.service.TSysLogSvc;
import com.fufan.mtsaas.modules.base.sysmsg.dao.TSysMessageDao;
import com.fufan.mtsaas.modules.base.sysmsg.model.TSysMessage;
import com.fufan.mtsaas.modules.common.bo.request.ResultPack;
import com.fufan.mtsaas.modules.common.bo.response.RequestPojo;
import com.fufan.mtsaas.modules.common.bo.response.ResStatus;
import com.fufan.mtsaas.modules.common.bo.response.Result;
import com.fufan.mtsaas.modules.base.processinfo.dao.PProcessInfoDao;
import com.fufan.mtsaas.modules.base.processinfo.model.PProcessInfo;
import com.fufan.mtsaas.modules.sysmgr.syuser.bo.request.UserGroupQueryRequest;
import com.fufan.mtsaas.modules.sysmgr.syuser.model.SYuserInfo;
import com.fufan.mtsaas.modules.sysmgr.tsysparam.bo.CheckItemBo;
import com.fufan.mtsaas.modules.sysmgr.tsysparam.bo.CirculationStatusBo;
import com.fufan.mtsaas.modules.sysmgr.tsysparam.bo.ConditionItemBo;
import com.fufan.mtsaas.modules.sysmgr.tsysparam.bo.ProcessItemBo;
import com.fufan.mtsaas.modules.sysmgr.tsysparam.dao.TSysParamDao;
import com.fufan.mtsaas.modules.sysmgr.tsysparam.model.TSysParam;
import com.fufan.mtsaas.modules.newtech.xjstech.bo.request.*;
import com.fufan.mtsaas.modules.newtech.xjstech.bo.response.XjsDeptInfoResponse;
import com.fufan.mtsaas.modules.newtech.xjstech.bo.response.XjsTechResponse;
import com.fufan.mtsaas.modules.newtech.xjstech.bo.response.XjsTechTotal;
import com.fufan.mtsaas.modules.newtech.xjstech.bo.response.XjsThisUserInfo;
import com.fufan.mtsaas.modules.newtech.xjstech.dao.XjsTechDao;
import com.fufan.mtsaas.modules.newtech.xjstech.model.XjsTech;
import com.fufan.mtsaas.modules.newtech.xjstech.service.XjsTechSvc;
import com.fufan.mtsaas.modules.newtech.xjstechhis.bo.request.XjsTechHisQueryRequest;
import com.fufan.mtsaas.modules.newtech.xjstechhis.bo.response.XjsTechHisResponse;
import com.fufan.mtsaas.modules.newtech.xjstechhis.dao.XjsTechHisDao;
import com.fufan.mtsaas.modules.newtech.xjsyearaudit.dao.XjsYearAuditDao;
import com.fufan.mtsaas.modules.newtech.xjsyearaudit.model.XjsYearAudit;
import com.fufan.mtsaas.modules.sysmgr.sydept.dao.SYDeptDao;
import com.fufan.mtsaas.modules.sysmgr.sydept.model.SYDept;
import com.fufan.mtsaas.modules.sysmgr.syuser.dao.SYuserDao;
import com.fufan.mtsaas.modules.sysmgr.syuser.model.SYuser;
import com.fufan.mtsaas.tools.AESTool;
import com.fufan.mtsaas.tools.ExcelCreateUtil;
import com.fufan.mtsaas.tools.ExcelData;
import com.fufan.mtsaas.util.*;
import com.github.pagehelper.ISelect;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Liby
 * @since 2024-12-16
 */
@Service("XjsTechSvcImpl")
@Slf4j
@Primary
public class XjsTechSvcImpl extends ServiceImpl<XjsTechDao, XjsTech> implements XjsTechSvc {
    /**
     * 数据库操作
     */
    @Autowired
    private XjsTechDao entitymDao;

    @Autowired
    private SYuserDao userDao;

    @Autowired
    private SYDeptDao deptDao;

    /**
     * 审批历史表
     */
    @Autowired
    private PProcessInfoDao pProcessInfoDao;


    @Autowired
    private TSysParamDao tsParamDao;

    @Autowired
    private TSysMessageDao tsMessageDao;

    /**
     * 年审表
     */
    @Autowired
    private XjsYearAuditDao xjsYearAuditDao;

    /**
     * 新项目历史表
     */
    @Autowired
    private XjsTechHisDao xjsTechHisDao;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private TSysLogSvc tSysLogSvc;

    @Autowired
    private SMSSender smsSender;
    @Autowired
    private ParamUtil paramUtil;
    @Autowired
    private RedissonCommand redissonCommand;

    @Override
    public Result<XjsThisUserInfo> doThisUserInfo(RequestPojo requestPojo) {
        Result<XjsThisUserInfo> result = new Result<>();
        Page<XjsThisUserInfo> page = new Page<>();

        XjsThisUserInfo userInfo = new XjsThisUserInfo();
        // 部门信息，页面提交数据
        SYuser user = userDao.selectById(Long.valueOf(requestPojo.getSysId()));
        if (null != user) {
            BeanUtils.copyProperties(user, userInfo);
            SYDept dept = deptDao.selectById(Long.valueOf(user.getDepID()));
            if (null != dept) {
                userInfo.setDeptName(dept.getDepName());
                if (!Objects.isNull(dept.getManager()) && dept.getManager() != 0) {
                    SYuser manager = userDao.selectById(dept.getManager());
                    if (null != manager) {
                        userInfo.setDeptManagerId(String.valueOf(manager.getId()));
                        userInfo.setDeptManagerName(manager.getName());
                    }
                }
            }
        }

        page.setRecords(Arrays.asList(userInfo));
        result.setResStatus(ResStatus.STATUS_SUCCESS);
        result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
        result.setResData(page);
        return result;
    }

    @Override
    public Result<XjsDeptInfoResponse> doDeptInfo(XjsTechIdRequest map) {
        Result<XjsDeptInfoResponse> result = new Result<>();
        if (null != map.getId()) {
            SYDept dept = deptDao.selectById(Long.valueOf(map.getId()));
            XjsDeptInfoResponse entitym = new XjsDeptInfoResponse();
            if (null != dept) {
                entitym.setDeptId(String.valueOf(dept.getId()));
                entitym.setDeptName(dept.getDepName());
                if (dept.getManager() != 0) {
                    SYuser manager = userDao.selectById(dept.getManager());
                    if (null != manager) {
                        entitym.setDeptManagerId(String.valueOf(manager.getId()));
                        entitym.setDeptManagerName(manager.getName());
                    }
                }
            }
            Page<XjsDeptInfoResponse> page = new Page<>();
            page.setRecords(Arrays.asList(entitym));
            result.setResData(page);
            result.setResStatus(ResStatus.STATUS_SUCCESS);
        } else {
            result.setResStatus(ResStatus.STATUS_UNAVAILABLE_MSG);
            result.setResMsg("部门ID为空");
            return result;
        }
        return result;
    }

    /**
     * 查询
     *
     * @param map 查询参数
     * @r Result.class
     */
    @Override
    public Result<XjsTechResponse> doQueryPage(XjsTechQueryRequest map, RequestPojo requestPojo) {
        Result<XjsTechResponse> result = new Result<>();

        // 当前用户ID
        String staffId = requestPojo.getSysId();
        map.setStaffId(staffId);

        // 我的申报
        map.setQueryType("myTech");

        Page<XjsTechResponse> page = new Page<>();
        long total = com.github.pagehelper.PageHelper.count(new ISelect() {
            @Override
            public void doSelect() {
                entitymDao.selectByPage(page, map);
            }
        });

        // 分页
        ParamUtil.setPage(map.getPageSize(), map.getCurrentPage(), page);
        //分页查询
        List<XjsTechResponse> list = entitymDao.selectByPage(page, map);

        page.setRecords(list);
        page.setTotal((int) total);
        result.setResStatus(ResStatus.STATUS_SUCCESS);
        result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
        result.setResData(page);
        return result;
    }

    /**
     * 获取项目编号
     *
     * @return
     */
    private String getProjectNo() {
        // 获取当前年
        int year = LocalDate.now().getYear();

        String no = stringRedisTemplate.opsForValue().get(RedisKeyConstant.ADD_PROJECT_NO);
        if (StringUtils.isBlank(no)) {
            no = year + "-001";
        } else {
            // 拆分项目编号以及校验
            String[] noArr = no.split("-");
            if (noArr.length != 2) {
                no = year + "-001";
                stringRedisTemplate.opsForValue().set(RedisKeyConstant.ADD_PROJECT_NO, no);
                return no;
            }
            int yearNo = Integer.parseInt(noArr[0]);
            int projectNo = Integer.parseInt(noArr[1]);
            // 当前年与redis中的年不一致，则重置为当前年
            if (year == yearNo) {
                projectNo += 1;
                if (projectNo < DefaultConstant.NUM_10) {
                    no = year + "-00" + projectNo;
                } else if (projectNo >= DefaultConstant.NUM_10 && projectNo < DefaultConstant.NUM_100) {
                    no = year + "-0" + projectNo;
                } else {
                    no = year + "-" + projectNo;
                }
            } else {
                // 当前年与redis中的年不一致，则重置为当前年
                no = year + "-001";
            }
        }
        // 设置到redis中
        stringRedisTemplate.opsForValue().set(RedisKeyConstant.ADD_PROJECT_NO, no);
        return no;
    }

    /**
     * 新增
     *
     * @param entitym
     * @return Result.class
     */
    @Override
    @Transactional
    public Result<XjsTech> doSave(XjsTechSaveRequest entitym, RequestPojo requestPojo) {
        Result<XjsTech> result = new Result<>();
        Page page = new Page();

        entitym.setCompanyId(Long.valueOf(requestPojo.getCustId()));

        try {
            // 如果ID为空，为新增，否则为编辑或者暂存
            if (null != entitym.getId()) {
                // 编辑，先获取原有的，删除原有的，然后直接进行新增
                XjsTech xjsTech = entitymDao.queryById(entitym.getId());
                if (null != xjsTech) {
                    // 删除原有数据
                    entitymDao.deleteById(entitym.getId());
                    // 复用创建时间
                    entitym.setCreateTime(xjsTech.getCreateTime());
//                    // 复用项目编号
//                    entitym.setProjectNo(xjsTech.getProjectNo());
                } else {
                    // 新增
                    entitym.setCreateTime(new Date());
                    // 获取项目编号
//                    if (DefaultConstant.NUM_1.equals(entitym.getProjectClass())) {
//                        entitym.setProjectNo(this.getProjectNo());
//                    } else {
//                        entitym.setProjectNo(this.getProjectNo() + "(X)");
//                    }
                }
                // 重置ID
                entitym.setId(null);
            } else {
                entitym.setCreateTime(new Date());
                // 获取项目编号
//                if (DefaultConstant.NUM_1.equals(entitym.getProjectClass())) {
//                    entitym.setProjectNo(this.getProjectNo());
//                } else {
//                    entitym.setProjectNo(this.getProjectNo() + "(X)");
//                }
            }

            String shortName = paramUtil.getTSysParam("HOSPITAL_NAME");
            if (Objects.nonNull(shortName) && shortName.equalsIgnoreCase("GSSY")) {
                RLock rLock = redissonCommand.getFairLock("SEQ_NO");
                if (rLock.tryLock()) {
                    try {
                        String seqNo = paramUtil.getTSysParam("SEQ_NO");
                        seqNo = "0000" + String.valueOf(Long.valueOf(seqNo) + 1);
                        seqNo = seqNo.substring(seqNo.length() - 4);
                        int rec = paramUtil.updateParam("SEQ_NO", seqNo);
                        entitym.setProjectNo(String.valueOf(DateUtil.getYear(new Date())) + "-" + seqNo);
                    } catch (Exception e) {
                        result.setResStatus(ResStatus.STATUS_DATABASE_FAIL);
                        result.setResMsg("SEQ_NO 异常 ：" + e.getMessage());
                    } finally {
                        rLock.unlock();
                    }
                }
            }

            // 最后的年审时间默认=创建时间
            entitym.setLastYearAuditTime(entitym.getCreateTime());

            // 用户相关
            entitym.setApplyUserId(Long.valueOf(requestPojo.getSysId()));
            entitym.setApplyUserName(requestPojo.getUserName());
            entitym.setCreateBy(requestPojo.getUserName());
            entitym.setUpdateBy(requestPojo.getUserName());
            entitym.setUpdateTime(new Date());

            // 部门信息，页面提交数据
            if (null != entitym.getApplyDeptId()) {
                SYDept dept = deptDao.selectById(entitym.getApplyDeptId());
                if (null != dept) {
                    if (dept.getManager() != 0) {
                        SYuser manager = userDao.selectById(dept.getManager());
                        if (null != manager) {
                            entitym.setApplyManagerId(Long.valueOf(String.valueOf(manager.getId())));
                            entitym.setApplyManagerName(manager.getName());
                        }
                    }
                }
            }

            // 其他信息
            entitym.setStatus(0);
            entitym.setNeedYearAudit(1);
            entitym.setAuditStatus(1);
            entitym.setIsEnabled(1);
            entitym.setDelFlag(0);

            int rec = entitymDao.insert(entitym);

//            result.setObjData(entitym);
            log.debug("新增数据返回 {}", rec);

            String content = DefaultConstant.NUM_1.equals(entitym.getStatus()) ? "暂存" : "提交";

            tSysLogSvc.saveLogInfo(Long.valueOf(entitym.getId()), "xjsproject", "新增项目", "项目名称:" + entitym.getName(), content, "成功", requestPojo);

            result.setResStatus(ResStatus.STATUS_SUCCESS);
            result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
            result.setResData(page.setRecords(Arrays.asList(entitym)));

        } catch (Exception e) {
            String content = DefaultConstant.NUM_1.equals(entitym.getStatus()) ? "暂存" : "提交";

            tSysLogSvc.saveLogInfo(Long.valueOf(entitym.getId()), "xjsproject", "新增项目", "项目名称:" + entitym.getName(), content, "失败", ParamUtil.doChange());

            log.error("新增数据出错", e);
            result.setResStatus(ResStatus.STATUS_DATABASE_FAIL);
            result.setResMsg("新增数据出错：" + e.getMessage());
        }
        return result;

    }

    /**
     * 修改
     *
     * @param entitym
     * @param requestPojo
     * @return Result.class
     */
    @Override
    @Transactional
    public Result doUpdate(XjsTechSaveRequest entitym, RequestPojo requestPojo) {
        Result result = new Result();

        // 提交
        // 1.获取原有信息，并修改状态
        XjsTech xjsTech = entitymDao.selectById(entitym.getId());
        //1-草稿或4-已驳回
        if (xjsTech == null || !(xjsTech.getAuditStatus() == 1 || xjsTech.getAuditStatus() == 4)) {
            result.setResStatus(ResStatus.STATUS_WRONGFUL);
            result.setResMsg("数据不存在或状态不允许进行提交");
            return result;
        }
        XjsTech update = new XjsTech();
        update.setId(entitym.getId());
        update.setAuditStatus(2);
        update.setStatus(10);
        update.setUpdateBy(requestPojo.getUserName());
        update.setUpdateTime(new Date());
        entitymDao.updateById(update);

        // 提交流程,流转到部门负责人
        PProcessInfo pProcessInfo = new PProcessInfo();
        pProcessInfo.setCorrelationId(entitym.getId());
        pProcessInfo.setCreateTime(new Date());
        pProcessInfo.setTaskName("部门负责人审核");
        pProcessInfo.setCategory(1);
        pProcessInfo.setProcessStatus(10);
        pProcessInfo.setProcessBy(xjsTech.getApplyManagerName());
        pProcessInfo.setProcessOper("部门负责人审核");
        pProcessInfo.setProcessUserId(xjsTech.getApplyManagerId());
        pProcessInfo.setStatus(0);
        pProcessInfoDao.insert(pProcessInfo);

        // 存历史消息表
        TSysMessage tsMessage = new TSysMessage();
        tsMessage.setRelatedId(xjsTech.getId());
        tsMessage.setRelatedType("审批");
        tsMessage.setLogTitle("项目技术流程审批");
        tsMessage.setLogContent("您有一条" + xjsTech.getName() + "新技术新项目待审批");
        tsMessage.setCreateBy(String.valueOf(xjsTech.getApplyManagerId()));
        tsMessage.setCreateTime(new Date());
        tsMessage.setOperateStatus(DefaultConstant.NUM_0);
        tsMessageDao.insert(tsMessage);

        // 发短信:
        SYuser thisUser = userDao.selectById(xjsTech.getApplyManagerId());
        XjsTechSendSmaRequest sendSms = new XjsTechSendSmaRequest();
        try {
            sendSms.setTel(AESTool.decrypt(thisUser.getPhoneNo()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (null != sendSms.getTel()) {
            sendSms.setCustomerID(thisUser.getUserID());
            sendSms.setCustomerName(thisUser.getName());
            sendSms.setCustomerType("1");
            sendSms.setSrvType("XJS");
            sendSms.setMessage(SMSSender.getContent(thisUser.getName(), xjsTech.getName(), 10));
            smsSender.sendSms(sendSms);
        }

        tSysLogSvc.saveLogInfo(Long.valueOf(entitym.getId()), "xjsproject", "新增项目", "项目名称:" + entitym.getName(), "提交", "成功", ParamUtil.doChange());

        result.setResStatus(ResStatus.STATUS_SUCCESS);
        result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
        return result;

    }

    /**
     * 删除
     *
     * @param map
     * @return Result.class
     */
    @Override
    @Transactional
    public Result doDelete(XjsTechDeleteRequest map, RequestPojo requestPojo) {
        Result result = new Result();
        // 提交
        // 1.获取原有信息，并修改状态
        XjsTech xjsTech = entitymDao.selectById(map.getId());
        if (xjsTech == null || xjsTech.getDelFlag() == 1) {
            result.setResStatus(ResStatus.STATUS_WRONGFUL);
            result.setResMsg("数据已删除");
            return result;
        }
        entitymDao.deleteById(map.getId());

        tSysLogSvc.saveLogInfo(Long.valueOf(map.getId()), "xjsproject", "删除项目", "项目名称:" + xjsTech.getName(), "删除", "成功", requestPojo);

        result.setResStatus(ResStatus.STATUS_SUCCESS);
        result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);

        return result;

    }

    /**
     * 详情
     *
     * @param map
     * @param requestPojo
     * @return
     */
    @Override
    public Result doDetail(XjsTechQueryByIdRequest map, RequestPojo requestPojo) {
        Result<XjsTechResponse> result = new Result();
        XjsTech xjsTech = entitymDao.queryById(map.getId());
        if (null != xjsTech) {
            result.setResStatus(ResStatus.STATUS_SUCCESS);
            result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);

            // 获取所有审批人，更新当前审批人审批状态
            PProcessInfo processFilter = new PProcessInfo();
            processFilter.setCorrelationId(xjsTech.getId());
            processFilter.setCategory(1);
            List<PProcessInfo> pProcessInfos = pProcessInfoDao.queryAll(processFilter);

            XjsTechResponse xjsTechResponse = new XjsTechResponse();
            BeanUtils.copyProperties(xjsTech, xjsTechResponse);
            xjsTechResponse.setProcessInfoList(pProcessInfos);
            Page page = new Page();
            result.setResData(page.setRecords(Arrays.asList(xjsTechResponse)));
        } else {
            result.setResStatus(ResStatus.STATUS_UNAVAILABLE);
            result.setResMsg(ResStatus.STATUS_UNAVAILABLE_MSG);
        }
        return result;
    }

    /**
     * 我的草稿
     *
     * @param map
     * @param requestPojo
     * @return
     */
    @Override
    public Result doMyDraftQuery(XjsTechQueryRequest map, RequestPojo requestPojo) {
        Result<XjsTechResponse> result = new Result<>();

        // 当前用户ID
        String staffId = requestPojo.getSysId();
        map.setStaffId(staffId);

        // 我的草稿
        map.setQueryType("myDraft");

        Page<XjsTechResponse> page = new Page<>();
        long total = com.github.pagehelper.PageHelper.count(new ISelect() {
            @Override
            public void doSelect() {
                entitymDao.selectByPage(page, map);
            }
        });

        // 分页
        ParamUtil.setPage(map.getPageSize(), map.getCurrentPage(), page);
        //分页查询
        List<XjsTechResponse> list = entitymDao.selectByPage(page, map);

        page.setRecords(list);
        page.setTotal((int) total);
        result.setResStatus(ResStatus.STATUS_SUCCESS);
        result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
        result.setResData(page);
        return result;
    }

    /**
     * 已开通项目
     *
     * @param map
     * @param requestPojo
     * @return
     */
    @Override
    public Result doOpenedProjectQuery(XjsTechQueryRequest map, RequestPojo requestPojo) {
        Result<XjsTechResponse> result = new Result<>();

        // 当前用户ID
        String staffId = requestPojo.getSysId();
        map.setStaffId(staffId);

        // 已开通项目
        map.setQueryType("openedProject");

        Page<XjsTechResponse> page = new Page<>();
        long total = com.github.pagehelper.PageHelper.count(new ISelect() {
            @Override
            public void doSelect() {
                entitymDao.selectByPage(page, map);
            }
        });

        // 分页
        ParamUtil.setPage(map.getPageSize(), map.getCurrentPage(), page);
        //分页查询
        List<XjsTechResponse> list = entitymDao.selectByPage(page, map);

        page.setRecords(list);
        page.setTotal((int) total);
        result.setResStatus(ResStatus.STATUS_SUCCESS);
        result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
        result.setResData(page);
        return result;
    }

    /**
     * 导出已开通项目
     *
     * @param queryRequest
     * @param requestPojo
     * @param response
     * @return
     */
    @Override
    public Result doExportOpenedProject(XjsTechQueryRequest queryRequest, RequestPojo requestPojo, HttpServletResponse response) {

        ResultPack resultPack = new ResultPack();
        Result result = new Result();
        ExcelData excelData = new ExcelData();
        excelData.setName("已开通的项目");
        String[] title = {"项目名称", "项目分类", "申报日期", "开通日期", "年审状态"};
        Page<XjsTechResponse> page = new Page<>();
        // 当前用户ID
        String staffId = requestPojo.getSysId();
        queryRequest.setStaffId(staffId);

        // 已开通项目
        queryRequest.setQueryType("openedProject");
        List<XjsTechResponse> list = entitymDao.selectByPage(page, queryRequest);
        List<List<Object>> rows = new ArrayList<>();

        // HashMap 转换为 List<Object>
        for (XjsTechResponse item : list) {
            Map<String, Object> mapEntrys = new HashMap<>();
            mapEntrys.put("项目名称", item.getName());
            if (DefaultConstant.NUM_1.equals(item.getProjectClass())) {
                mapEntrys.put("项目分类", "非限制类");
            } else if (DefaultConstant.NUM_2.equals(item.getProjectClass())) {
                mapEntrys.put("项目分类", "限制类");
            } else {
                mapEntrys.put("项目分类", "上海首家");
            }
            // Date 转字符串
            if (item.getCreateTime() != null) {
                mapEntrys.put("申报日期", DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", item.getCreateTime()));
            }
            if (item.getOpenTime() != null) {
                mapEntrys.put("开通日期", DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", item.getOpenTime()));
            }
            mapEntrys.put("年审状态", "需年审");

            List<Object> row = new ArrayList<>();
            row.addAll(mapEntrys.values());
            rows.add(row);
        }

        List<String> titles = Arrays.asList(title);
        excelData.setTitles(titles);
        excelData.setRows(rows);
        String filename = String.valueOf(System.currentTimeMillis());
        ExcelCreateUtil.exportExcel(response, "openedProject" + filename + ".xls", excelData);

        tSysLogSvc.saveLogInfo(0, "xjsproject", "导出项目", "", "导出", "成功", requestPojo);

        result.setResStatus(ResStatus.STATUS_SUCCESS);
        result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);

        return resultPack.doResultPack(result, "", "111111");
    }

    /**
     * 待我审批的
     *
     * @param map
     * @param requestPojo
     * @return
     */
    @Override
    public Result doPendingApprovalQuery(XjsTechQueryRequest map, RequestPojo requestPojo) {
        Result<XjsTechResponse> result = new Result<>();

        // 当前用户ID
        String staffId = requestPojo.getSysId();
        map.setStaffId(staffId);

        // 待我审批的
        map.setQueryType("waitingApproval");

        Page<XjsTechResponse> page = new Page<>();
        long total = com.github.pagehelper.PageHelper.count(new ISelect() {
            @Override
            public void doSelect() {
                entitymDao.selectByProcessAndPage(page, map);
            }
        });

        // 分页
        ParamUtil.setPage(map.getPageSize(), map.getCurrentPage(), page);
        //分页查询
        List<XjsTechResponse> list = entitymDao.selectByProcessAndPage(page, map);

        page.setRecords(list);
        page.setTotal((int) total);
        result.setResStatus(ResStatus.STATUS_SUCCESS);
        result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
        result.setResData(page);
        return result;
    }

    /**
     * 我已审批的
     *
     * @param map
     * @param requestPojo
     * @return
     */
    @Override
    public Result doAlreadyApprovedQuery(XjsTechQueryRequest map, RequestPojo requestPojo) {
        Result<XjsTechResponse> result = new Result<>();

        // 当前用户ID
        String staffId = requestPojo.getSysId();
        map.setStaffId(staffId);

        // 我已审批的
        map.setQueryType("alreadyApproved");

        Page<XjsTechResponse> page = new Page<>();
        long total = com.github.pagehelper.PageHelper.count(new ISelect() {
            @Override
            public void doSelect() {
                entitymDao.selectByProcessAndPage(page, map);
            }
        });

        // 分页
        ParamUtil.setPage(map.getPageSize(), map.getCurrentPage(), page);
        //分页查询
        List<XjsTechResponse> list = entitymDao.selectByProcessAndPage(page, map);

        page.setRecords(list);
        page.setTotal((int) total);
        result.setResStatus(ResStatus.STATUS_SUCCESS);
        result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
        result.setResData(page);
        return result;
    }

    /**
     * 审批
     *
     * @param map
     * @param requestPojo
     * @return
     */
    @Transactional
    @Override
    public Result doApprove(XjsTechApproveRequest map, RequestPojo requestPojo) {
        Result result = new Result<>();
        // 1.获取当前项目信息,当前节点信息
        XjsTech xjsTech = entitymDao.queryById(map.getId());
        if (Objects.isNull(xjsTech)) {
            result.setResStatus(ResStatus.STATUS_WRONGFUL);
            result.setResMsg(ResStatus.STATUS_WRONGFUL_MSG + " id记录不存在，请检查");
            return result;
        }

        //1-草稿或4-已驳回
        if ((xjsTech.getAuditStatus() == 1 || xjsTech.getAuditStatus() == 4)) {
            result.setResStatus(ResStatus.STATUS_WRONGFUL);
            result.setResMsg("状态不允许进行提交");
            return result;
        }

        TSysParam hosName = getTSysParam("HOSPITAL_NAME");
        String shortName = hosName.getParamValue();

        // 2.编辑当前审核人审核状态
        // 所有的流程状态
        TSysParam status = getTSysParam(shortName + "_XJS_CIRCULATION_STATUS");
        List<CirculationStatusBo> circleStatus = null;
        if (status != null) {
            String statusJson = status.getParamValue();
            ObjectMapper mapper = new ObjectMapper();
            try {
                circleStatus = mapper.readValue(statusJson, new TypeReference<List<CirculationStatusBo>>() {
                });
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (CollectionUtils.isEmpty(circleStatus)) {
            result.setResStatus(ResStatus.STATUS_UNAVAILABLE);
            result.setResMsg(ResStatus.STATUS_UNAVAILABLE_MSG);
            return result;
        }
        // 当前节点
        CirculationStatusBo thisStatus = circleStatus.stream().filter(a -> a.getKey().equals(xjsTech.getStatus())).findFirst().orElse(null);
        if (null == thisStatus) {
            result.setResStatus(ResStatus.STATUS_UNAVAILABLE);
            result.setResMsg(ResStatus.STATUS_UNAVAILABLE_MSG);
            return result;
        }

        //20250223：并行节点数据加载
        HashMap<Integer, Integer> hsPararell = new HashMap();
//        hsPararell.put(30, 20);
//        hsPararell.put(120, 20);
        // 分组并计数
        Map<Integer, Long> grouped = circleStatus.stream()
                .collect(Collectors.groupingBy(item -> item.getKey(), Collectors.counting()));
        if (Objects.nonNull(grouped)) {
            Integer parallelKey = null;
            Set keySet = grouped.keySet();
            for (Object key : keySet) {
                if (grouped.get(key) > 1) {
                    parallelKey = (Integer) key;
                    break;
                }
            }
            Integer finalParallelKey = parallelKey;
            List<CirculationStatusBo> circleStatusParallel = circleStatus.stream().filter(item -> item.getKey().equals(finalParallelKey)).collect(Collectors.toList());
            for (CirculationStatusBo item : circleStatusParallel) {
                hsPararell.put(item.getNextKey(), item.getKey());
            }
        }


        //获取流转人员信息，新增下一次需要审核的人员名单
        TSysParam info = getTSysParam(shortName + "_XJS_FLOW");
        // 数据类型转换
        String infoJson = info.getParamValue();
        ObjectMapper mapper = new ObjectMapper();
        List<ProcessItemBo> processItems = null;
        try {
            processItems = mapper.readValue(infoJson, new TypeReference<List<ProcessItemBo>>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
            result.setResStatus(ResStatus.STATUS_FAILED);
            result.setResMsg(ResStatus.STATUS_FAILED_MSG + " 转化格式异常 " + e.getLocalizedMessage());
            return result;
        }

        // 当前用户ID
        String staffId = requestPojo.getSysId();
        // 获取所有审批人，更新当前审批人审批状态
        PProcessInfo processFilter = new PProcessInfo();
        processFilter.setCorrelationId(xjsTech.getId());
        List<PProcessInfo> pProcessInfos = pProcessInfoDao.queryAll(processFilter);
        if (CollectionUtils.isNotEmpty(pProcessInfos)) {
            // 此数据用户信息
            SYuser thisUser = userDao.selectById(xjsTech.getApplyUserId());

            // 是否是当前人审批
            boolean isApproval = false;

            //20250223：判断并行节点是否都已审批完成，如没有，则不能进行其他节点审批
            int count = 0;
            int appoveCount = 0;
            List<CirculationStatusBo> circulationStatusBoList = new ArrayList<>();
            circulationStatusBoList = circleStatus.stream().filter(a -> a.getKey().equals(xjsTech.getStatus())).collect(Collectors.toList());
            for (PProcessInfo item : pProcessInfos) {
                //20250223：并行节点重新获取thisStatus
                if (item.getProcessStatus().equals(xjsTech.getStatus()) && hsPararell.containsKey(item.getProcessStatus())) {
                    if (item.getStatus() == 1) {
                        count++;
                    }

                    if (item.getStatus() == 0 && item.getProcessUserId().equals(Long.valueOf(staffId))) {
                        thisStatus = circleStatus.stream().filter(a -> a.getKey().equals(item.getProcessStatus())).findFirst().orElse(null);
                    }
                }
                //20250223：判断并行节点有一个已审批完成
//                if(CollectionUtils.isNotEmpty(circulationStatusBoList)
//                        && item.getProcessStatus().equals(thisStatus.getKey())
//                        && item.getStatus() != 0){
//                    for(int i = 0; i < circulationStatusBoList.size(); i++) {
//                        if (item.getProcessStatus().equals(circulationStatusBoList.get(i).getKey())) {
//                            circulationStatusBoList.remove(i);
//                        }
//                    }
//                    appoveCount ++ ;
//                }
            }

//            if(appoveCount > 1 && CollectionUtils.isNotEmpty(circulationStatusBoList)){
//                thisStatus = circulationStatusBoList.get(0);
//            }

            if (count > 0 && count < hsPararell.size() && !hsPararell.containsKey(thisStatus.getKey())) {
                result.setResStatus(ResStatus.STATUS_EXIST_APPROVAL);
                result.setResMsg(ResStatus.STATUS_APPROVAL_MSG);
                return result;
            }

            for (PProcessInfo item : pProcessInfos) {
                //20250223：判断并行节点
                if (staffId.equals(String.valueOf(item.getProcessUserId())) &&
                        (xjsTech.getStatus().equals(item.getProcessStatus())
                                || hsPararell.containsKey(item.getProcessStatus()) == true)) {
                    isApproval = true;

                    item.setStatus(1);
                    item.setRemarks(map.getRemarks());
                    item.setUpdateTime(new Date());
                    item.setTask(map.getTask());
                    item.setAuditStatus(DefaultConstant.NUM_1.equals(map.getAuditStatus()) ? 1 : 2);
                    pProcessInfoDao.updateById(item);

                    // 存历史消息表
                    TSysMessage tsMessage = new TSysMessage();
                    tsMessage.setRelatedId(xjsTech.getId());
                    tsMessage.setRelatedType("审批");
                    tsMessage.setLogTitle("项目技术流程审批");
                    String content = DefaultConstant.NUM_1.equals(item.getAuditStatus()) ? "审批通过" : "审批驳回";
                    tsMessage.setLogContent(xjsTech.getName() + "流程审批" + thisStatus.getName() + content);
                    tsMessage.setCreateBy(String.valueOf(xjsTech.getApplyUserId()));
                    tsMessage.setCreateTime(new Date());
                    tsMessage.setOperateStatus(DefaultConstant.NUM_0);
                    tsMessageDao.insert(tsMessage);

                    // 发短信:  定制化： 流转中的任意一个结点完成审批后是驳回拒绝的结果
                    XjsTechSendSmaRequest sendSms = new XjsTechSendSmaRequest();
                    try {
                        sendSms.setTel(AESTool.decrypt(thisUser.getPhoneNo()));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    if (null != sendSms.getTel()) {
                        sendSms.setCustomerID(thisUser.getUserID());
                        sendSms.setCustomerName(thisUser.getName());
                        sendSms.setCustomerType("1");
                        sendSms.setSrvType("XJS");
                        sendSms.setMessage(SMSSender.getContent(thisUser.getName(), xjsTech.getName(), 1100));
                        smsSender.sendSms(sendSms);
                    }

                    // 驳回，不进行任何操作
                    boolean handleReject = HandleReject(xjsTech, shortName, item, pProcessInfos, thisStatus);
                    if (handleReject) {
//                    if (DefaultConstant.NUM_2.equals(item.getAuditStatus())) {
                        // 驳回，不进行任何操作
                        xjsTech.setAuditStatus(DefaultConstant.NUM_4);
                        entitymDao.updateById(xjsTech);
                        result.setResStatus(ResStatus.STATUS_SUCCESS);
                        result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
                        return result;
                    }
                }
            }

            if (!isApproval) {
                result.setResStatus(ResStatus.STATUS_EXIST_APPROVAL);
                result.setResMsg(ResStatus.STATUS_APPROVAL_MSG);
                return result;
            }
        } else {
            result.setResStatus(ResStatus.STATUS_EXIST_APPROVAL);
            result.setResMsg(ResStatus.STATUS_APPROVAL_MSG);
            return result;
        }

        //  3.如果当前节点多人审批，需要通过投票的方式，当通过人数大于百分之多少时，确定流程是否进行下一步流转
        // 当前流程总人数
        Long total = pProcessInfos.stream().filter(a -> null != a.getProcessStatus() && a.getProcessStatus().equals(xjsTech.getStatus())).count();
        // 通过人数
        Long pass = pProcessInfos.stream().filter(a -> null != a.getProcessStatus() && a.getProcessStatus().equals(xjsTech.getStatus()) && DefaultConstant.NUM_1.equals(a.getAuditStatus())).count();

        boolean passFlag = HandleApprove(xjsTech, shortName, pProcessInfos, thisStatus);

        // 标准：2/3通过，参数比例
        if (passFlag) {
//        if (pass.doubleValue() / total.doubleValue() >= xjsScore) {
            // 当前节点若还有其他人待审批的改为无需处理
            pProcessInfos.stream().filter(a -> DefaultConstant.NUM_0.equals(a.getStatus()) &&
                    null != a.getProcessStatus() && a.getProcessStatus().equals(xjsTech.getStatus())).forEach(a -> {
                a.setStatus(2);
                a.setUpdateTime(new Date());
                pProcessInfoDao.updateById(a);
            });


            if (info != null) {
                // 没有下个节点了
                if (null == thisStatus.getNextKey()) {
                    // 5.修改当前项目的下一个节点状态为年审
                    xjsTech.setStatus(80);
                    // 已完结状态
                    xjsTech.setAuditStatus(DefaultConstant.NUM_3);
                    entitymDao.updateById(xjsTech);

                    result.setResStatus(ResStatus.STATUS_SUCCESS);
                    result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
                    return result;
                }

                // 4.业务操作：需要进行消息发送、短信发送、操作审批的人员集合
                List<SYuser> syuserList = new ArrayList<>();

                // 获取下一个节点，人员名单
                //20250223：支持下一个节点，可能是并行节点
                List<CirculationStatusBo> nextStatusList = new ArrayList<>();
//                List<CirculationStatusBo> nextStatusList = circleStatus.stream().filter(a -> a.getKey().equals(thisStatus.getNextKey())).collect(Collectors.toList());
//                CirculationStatusBo nextStatus = circleStatus.stream().filter(a -> a.getKey().equals(thisStatus.getNextKey())).findFirst().orElse(null);
                boolean pararellFlag = false;
                Integer statusNextKey = thisStatus.getNextKey();
                Integer statusKey = thisStatus.getKey();
                if (hsPararell.containsKey(statusNextKey)) {
                    List<CirculationStatusBo> nextStatusListTemp = circleStatus.stream().filter(a -> a.getKey().equals(statusKey)).collect(Collectors.toList());
                    for (CirculationStatusBo item : nextStatusListTemp) {
                        CirculationStatusBo nextStatus = circleStatus.stream().filter(a -> a.getKey().equals(item.getNextKey())).findFirst().orElse(null);
                        nextStatusList.add(nextStatus);
                    }
                    pararellFlag = true;
                } else {
                    CirculationStatusBo nextStatus = circleStatus.stream().filter(a -> a.getKey().equals(statusNextKey)).findFirst().orElse(null);
                    nextStatusList.add(nextStatus);
                }
                int itemStatus = -1;
                for (CirculationStatusBo nextStatus : nextStatusList) {
                    itemStatus++;
                    syuserList = new ArrayList<>();
                    if (Objects.isNull(nextStatus)) {
                        continue;
                    }
                    for (ProcessItemBo item : processItems) {
                        // 当前节点信息
                        System.out.println("Process: " + item.getProcess());
                        // 当前节点的下一个节点
                        if (Objects.isNull(item.getProcess())
                                || !item.getProcess().equals(nextStatus.getKey())) {
                            continue;
                        }

                        // 当前节点所涉及到的人员ID
                        if (item.getSyuser() != null) {
                            for (ProcessItemBo.SyUserId user : item.getSyuser()) {
                                System.out.println("User ID: " + user.getId());
                                SYuser sYuser = userDao.selectById(user.getId());
                                if (sYuser == null) {
                                    continue;
                                }
                                syuserList.add(sYuser);
                            }
                        }
                        // 当前节点所涉及到的部门ID
                        if (CollectionUtils.isNotEmpty(item.getSydept())) {
                            for (ProcessItemBo.SyDeptId dept : item.getSydept()) {
                                System.out.println("Manager: " + dept.getManager());
                                Page page = new Page();
                                HashMap userFilter = new HashMap<>();
                                userFilter.put("DepID", dept.getManager());
                                List<SYuser> syuser = userDao.selectList(page, userFilter);
                                syuserList.addAll(syuser);
                            }
                        }

                        // 当前节点所涉及到的组ID
                        if (CollectionUtils.isNotEmpty(item.getSygrouph())) {
                            getCheckUser(xjsTech, syuserList, item);

                            for (ProcessItemBo.SyGroupId group : item.getSygrouph()) {
                                System.out.println("Group ID: " + group.getId());
                                Page page = new Page();
                                HashMap userFilter = new HashMap<>();
                                userFilter.put("UserGroupID", group.getId());
                                List<SYuser> syuser = userDao.selectList(page, userFilter);
                                syuserList.addAll(syuser);
                            }

                            getGroupRelatedUsers(syuserList, item);
                        }
                    }

                    //2025041 判断是否有条件，获取其他节点数据
                    nextStatus = checkCondition(nextStatus, circleStatus, xjsTech);
                    //替换节点数据;
                    nextStatusList.set(itemStatus, nextStatus);

                    // 进行业务操作，消息发送、短信发送、提交流程审批
                    for (SYuser sYuser : syuserList) {
                        //20250223：判定是否已存在（用户+流程节点）
                        int currKey = nextStatus.getKey();
                        total = pProcessInfos.stream().filter(a -> null != a.getProcessStatus()
                                && a.getProcessStatus().equals(currKey)
                                && a.getProcessUserId().equals(Long.valueOf(sYuser.getId()))).count();
                        if (total > 0) {
                            continue;
                        }

                        // 提交流程
                        PProcessInfo pProcessInfo = new PProcessInfo();
                        pProcessInfo.setCorrelationId(xjsTech.getId());
                        pProcessInfo.setCreateTime(new Date());
                        pProcessInfo.setTaskName(nextStatus.getName() + "审核");
                        pProcessInfo.setCategory(1);
                        pProcessInfo.setProcessStatus(nextStatus.getKey());
                        pProcessInfo.setProcessBy(sYuser.getName());
                        pProcessInfo.setProcessUserId(Long.valueOf(sYuser.getId()));
                        pProcessInfo.setProcessOper(nextStatus.getName() + "审核");
                        pProcessInfo.setStatus(0);
                        pProcessInfoDao.insert(pProcessInfo);

                        //将当前节点加入作为判定数据
                        pProcessInfos.add(pProcessInfo);

                        // 发送短信：给相应的下一阶段审核人
                        XjsTechSendSmaRequest sendSms = new XjsTechSendSmaRequest();
                        try {
                            sendSms.setTel(AESTool.decrypt(sYuser.getPhoneNo()));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        if (null != sendSms.getTel()) {
                            sendSms.setCustomerID(sYuser.getEmpNo());
                            sendSms.setCustomerName(sYuser.getName());
                            sendSms.setCustomerType("1");
                            sendSms.setSrvType("XJS");
                            sendSms.setMessage(SMSSender.getContent(sYuser.getName(), xjsTech.getName(), nextStatus.getKey()));
                            smsSender.sendSms(sendSms);
                        }

                        // 存历史消息表
                        TSysMessage tsMessage = new TSysMessage();
                        tsMessage.setRelatedId(xjsTech.getId());
                        tsMessage.setRelatedType("审批");
                        tsMessage.setLogTitle("项目技术流程审批");
                        tsMessage.setLogContent("您有一条" + xjsTech.getName() + "新技术新项目待审批");
                        tsMessage.setCreateBy(String.valueOf(sYuser.getId()));
                        tsMessage.setCreateTime(new Date());
                        tsMessage.setOperateStatus(DefaultConstant.NUM_0);
                        tsMessageDao.insert(tsMessage);
                    }
                }

                // 需要填上开通时间
                if (null != map.getOpenTime()) {
                    xjsTech.setOpenTime(map.getOpenTime());
                    xjsTech.setYearAuditNum(1);
                }

                if (CollectionUtils.isNotEmpty(nextStatusList)) {
                    // 5.修改当前项目的下一个节点状态
                    //20250223：获取并行另一个节点，更新状态
                    Integer nextKey = nextStatusList.get(0).getKey();
                    if (hsPararell.containsKey(thisStatus.getKey())) {
                        hsPararell.remove(thisStatus.getKey());
                        Set keySet = hsPararell.keySet();
                        for (Object key : keySet) {
                            for (PProcessInfo item : pProcessInfos) {
                                if (item.getProcessStatus().equals(key) && item.getStatus().equals(1)) {
                                    hsPararell.remove(key);
                                }
                            }
                        }
                        if (hsPararell.size() > 0) {
                            for (Object key : keySet) {
                                nextKey = (Integer) key;
                                break;
                            }
                        }
                    }
                    xjsTech.setStatus(nextKey);
//                    xjsTech.setStatus(nextStatus.getKey());
                    entitymDao.updateById(xjsTech);

                    // 6. 财务核价 -》医务处开通，这个是自动化流程，自动走流程
                    //20250223：并行节点取第一个
                    if (DefaultConstant.NUM_70.equals(nextKey) && CollectionUtils.isNotEmpty(syuserList)) {
//                    if (null != map.getOpenTime() && DefaultConstant.NUM_70.equals(nextStatus.getKey()) && CollectionUtils.isNotEmpty(syuserList)) {
                        RequestPojo pojo = new RequestPojo();
                        pojo.setSysId(String.valueOf(syuserList.get(0).getId()));
                        map.setAuditStatus(1);
                        map.setRemarks("系统自动通过");
                        map.setOpenTime(null);
                        map.setId(xjsTech.getId());
                        this.doApprove(map, pojo);
                    }
                }

                String content = DefaultConstant.NUM_1.equals(map.getAuditStatus()) ? "审批通过" : "审批驳回";

                tSysLogSvc.saveLogInfo(Long.valueOf(xjsTech.getId()), "xjsproject", "审批项目", "项目名称:" + xjsTech.getName(), content, "成功", requestPojo);
            }
        }

        result.setResStatus(ResStatus.STATUS_SUCCESS);
        result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
        return result;
    }

    /**
     * 20250401普陀需求：1.非限制类，节点为专家函审，其他类型为委员会评审
     *
     * @param nextStatus
     * @return
     */
    private CirculationStatusBo checkCondition(CirculationStatusBo nextStatus, List<CirculationStatusBo> circleStatus, XjsTech xjsTech) {
        CirculationStatusBo retStatus = new CirculationStatusBo();
        CirculationStatusBo checkItemBo = new CirculationStatusBo();
        BeanUtils.copyProperties(nextStatus, checkItemBo);
        Integer keyId = null;

        if (Objects.nonNull(checkItemBo.getCheck())) {
            try {
                ConditionItemBo conditionItemBo = checkItemBo.getCheck().getCondition();
                BeanWrapper wrapper = new BeanWrapperImpl(xjsTech);
                boolean resultFlag = false;
                Object nameValue = wrapper.getPropertyValue(conditionItemBo.getField());
                if (conditionItemBo.getExpress().equalsIgnoreCase("==")) {
                    resultFlag = nameValue.equals(Integer.valueOf(conditionItemBo.getValue()));
                } else if (conditionItemBo.getExpress().equalsIgnoreCase("!=")) {
                    resultFlag = !nameValue.equals(Integer.valueOf(conditionItemBo.getValue()));
                }
                if (resultFlag) {
                    List<ProcessItemBo.SyGroupId> listKeyId = checkItemBo.getCheck().getSygrouph();
                    log.debug("获取check 数据 " + listKeyId.toString());
                    keyId = Integer.valueOf(listKeyId.get(0).getId());
                }
            } catch (Exception ex) {
                log.error("解析表达式{" + checkItemBo.getCheck().toString() + "}异常： " + ex.getLocalizedMessage());
            }
        }

        if (Objects.nonNull(keyId)) {
            Integer finalKeyId = keyId;
            retStatus = circleStatus.stream().filter(a -> a.getKey().equals(finalKeyId)).findFirst().orElse(null);
        } else {
            BeanUtils.copyProperties(nextStatus, retStatus);
        }

        return retStatus;
    }

    /**
     * 20250401普陀需求：1、非限制类，管理委员会3人需全员完成审批并全部通过，才可流转到下一个审批节点；有1人驳回即驳回申请。
     * 2、限制类/首家，管理委员会20人需全员完成审批，且审批人员通过人数达到或超过管理委员会总人数的2/3，才可流转到下一个审批节点；
     * 不满足2/3及以上审批人员通过的情况，驳回申请。
     * 3、申请驳回后支持在原有申请基础上修改并重新提交，审批历史需包含驳回重新提交前后的所有记录。
     *
     * @param xjsTech
     * @param shortName
     * @param pProcessInfos
     * @param thisStatus
     * @return
     */
    private boolean HandleApprove(XjsTech xjsTech, String shortName, List<PProcessInfo> pProcessInfos, CirculationStatusBo thisStatus) {
        boolean passFlag = false;
        Double xjsScore = DefaultConstant.NUM_67;
        try {
            TSysParam scoreParam = getTSysParam("XJS_SCORE");
            if (Objects.nonNull(scoreParam) && Objects.nonNull(scoreParam.getParamValue())) {
                xjsScore = Double.valueOf(scoreParam.getParamValue());
            }
        } catch (Exception ex) {
        }

        // 当前流程总人数
        Long total = pProcessInfos.stream().filter(a -> null != a.getProcessStatus() && a.getProcessStatus().equals(xjsTech.getStatus())).count();
        // 通过人数
        Long pass = pProcessInfos.stream().filter(a -> null != a.getProcessStatus() && a.getProcessStatus().equals(xjsTech.getStatus()) && DefaultConstant.NUM_1.equals(a.getAuditStatus())).count();

        if (shortName.equalsIgnoreCase("PTZX")) {
            // 拒绝人数
            Long reject = pProcessInfos.stream().filter(a -> null != a.getProcessStatus() && a.getProcessStatus().equals(xjsTech.getStatus()) && DefaultConstant.NUM_2.equals(a.getAuditStatus())).count();
            // 项目分类 1-非限制类，2-限制类，3-上海首家
            if (xjsTech.getProjectClass() == 1) {
                if (pass.doubleValue() + reject.doubleValue() >= total.doubleValue()) {
                    passFlag = true;
                }
            } else {
                if ((pass.doubleValue() + reject.doubleValue() >= total.doubleValue()) && (pass.doubleValue() / total.doubleValue() >= xjsScore.doubleValue())) {
                    passFlag = true;
                }
            }
        } else {
            if (pass.doubleValue() / total.doubleValue() >= xjsScore.doubleValue()) {
                passFlag = true;
            }
        }

        return passFlag;
    }

    /**
     * 普通的拒绝，一个拒绝即停止审批；
     * 普陀:1、非限制类，管理委员会3人需全员完成审批并全部通过，才可流转到下一个审批节点；有1人驳回即停止审批。2.限制类 2/3 不通过则拒绝即停止审批；
     *
     * @param xjsTech
     * @param shortName
     * @param item
     * @param pProcessInfos
     * @param thisStatus
     * @return
     */
    private boolean HandleReject(XjsTech xjsTech, String shortName, PProcessInfo item, List<PProcessInfo> pProcessInfos, CirculationStatusBo thisStatus) {
        boolean rejectFlag = false;
        Double xjsScore = DefaultConstant.NUM_67;
        try {
            TSysParam scoreParam = getTSysParam("XJS_SCORE");
            if (Objects.nonNull(scoreParam) && Objects.nonNull(scoreParam.getParamValue())) {
                xjsScore = Double.valueOf(scoreParam.getParamValue());
            }
        } catch (Exception ex) {
        }

        // 当前流程总人数
        Long total = pProcessInfos.stream().filter(a -> null != a.getProcessStatus() && a.getProcessStatus().equals(xjsTech.getStatus())).count();
        // 通过人数
        Long pass = pProcessInfos.stream().filter(a -> null != a.getProcessStatus() && a.getProcessStatus().equals(xjsTech.getStatus()) && DefaultConstant.NUM_1.equals(a.getAuditStatus())).count();

        if (shortName.equalsIgnoreCase("PTZX")) {
            // 拒绝人数
            Long reject = pProcessInfos.stream().filter(a -> null != a.getProcessStatus() && a.getProcessStatus().equals(xjsTech.getStatus()) && DefaultConstant.NUM_2.equals(a.getAuditStatus())).count();
            // 项目分类 1-非限制类，2-限制类，3-上海首家
            if (xjsTech.getProjectClass() == 1 && reject.doubleValue() >= 1) {
                rejectFlag = true;
            } else {
                if ((pass.doubleValue() + reject.doubleValue() >= total.doubleValue()) && (pass.doubleValue() / total.doubleValue() < xjsScore.doubleValue())) {
                    rejectFlag = true;
                }
            }
        } else {
            if (DefaultConstant.NUM_2.equals(item.getAuditStatus())) {
                rejectFlag = true;
            }
        }

        return rejectFlag;
    }

    /**
     * 获取条件中的角色及用户
     *
     * @param xjsTech
     * @param syuserList
     * @param item
     */
    private void getCheckUser(XjsTech xjsTech, List<SYuser> syuserList, ProcessItemBo item) {
        if (Objects.nonNull(item.getCheck())) {
            try {
                CheckItemBo checkItemBo = item.getCheck();
                ConditionItemBo conditionItemBo = checkItemBo.getCondition();
                BeanWrapper wrapper = new BeanWrapperImpl(xjsTech);
                boolean resultFlag = false;
                Object nameValue = wrapper.getPropertyValue(conditionItemBo.getField());
                if (conditionItemBo.getExpress().equalsIgnoreCase("==")) {
                    resultFlag = nameValue.equals(Integer.valueOf(conditionItemBo.getValue()));
                } else if (conditionItemBo.getExpress().equalsIgnoreCase("!=")) {
                    resultFlag = !nameValue.equals(Integer.valueOf(conditionItemBo.getValue()));
                }
                if (resultFlag) {
                    item.setSygrouph(checkItemBo.getSygrouph());

                    log.debug("获取check 数据 " + checkItemBo.getSygrouph().toString());
                    getGroupRelatedUsers(syuserList, item);

                }
            } catch (Exception ex) {
                log.error("解析表达式{" + item.getCheck().toString() + "}异常： " + ex.getLocalizedMessage());
            }
        }
    }

    /**
     * 获取角色对应的用户列表
     *
     * @param syuserList
     * @param item
     */
    public List<SYuser> getGroupRelatedUsers(List<SYuser> syuserList, ProcessItemBo item) {
        //取角色对应的用户
        for (ProcessItemBo.SyGroupId group : item.getSygrouph()) {
            Page page = new Page();
            UserGroupQueryRequest queryRequest = new UserGroupQueryRequest();
            queryRequest.setUserGroupId(Long.valueOf(group.getId()));
            List<SYuserInfo> sYuserList = userDao.queryRoleUser(page, queryRequest);
            if (Objects.nonNull(sYuserList) && sYuserList.size() > 0) {
                for (int i = 0; i < sYuserList.size(); i++) {
                    SYuser sYuser = new SYuser();
                    BeanUtils.copyProperties(sYuserList.get(i), sYuser);
                    syuserList.add(sYuser);
                }
            }
        }
        return syuserList;
    }

    @Override
    public Result doSendSms(XjsTechSendSmaRequest map, RequestPojo requestPojo) {
        Result result = new Result<>();
        String info = smsSender.sendSms(map);
        result.setResMsg(info);
        result.setResStatus(ResStatus.STATUS_SUCCESS);
        return result;
    }

    /**
     * 获取系统参数
     *
     * @param paramName
     * @return
     */
    private TSysParam getTSysParam(String paramName) {
        TSysParam tsParam = new TSysParam();
        tsParam.setParamName(paramName);
        TSysParam info = tsParamDao.selectOne(tsParam);
        return info;
    }


    @Override
    public void addData() {
        // 年审定期任务
        // 1.年审规则：上海首家和限制类的每年都要，年审一年一次；非限制类的，就前2年审（当审完两次后，状态会被改为无需年审）。需要年审状态的数据
        // 2：获取满足条件的新项目
        Page<XjsTechResponse> page = new Page<>();
        XjsTechQueryRequest map = new XjsTechQueryRequest();
        map.setQueryType("needYearAudit");
        // 项目已开通，需要年审，创建时间在一年以前 且 定时器未执行过此条（最后一次年审时间在一年以前）
        // 根据当前时间往前推一年
        map.setLastYearAuditTime(DateUtils.addYears(new Date(), -1));
        List<XjsTechResponse> list = entitymDao.selectByPage(page, map);
        if (CollectionUtils.isNotEmpty(list)) {
            for (XjsTechResponse item : list) {
                // 复制数据插入到年审表中
                XjsYearAudit xjsYearAudit = new XjsYearAudit();
                BeanUtils.copyProperties(item, xjsYearAudit);

                // 新项目
                xjsYearAudit.setOtherType(1);
                xjsYearAudit.setAuditStatus(1);
                xjsYearAudit.setStatus(80);
                xjsYearAudit.setOtherId(item.getId());
//                xjsYearAudit.setApplyDeptId(item.getApplyDeptId());
//                xjsYearAudit.setApplyUserId(item.getApplyUserId());
//                xjsYearAudit.setApplyUserName(item.getApplyUserName());
                xjsYearAudit.setReportTime(item.getCreateTime());

                // 其他信息
                xjsYearAudit.setIsEnabled(1);
                xjsYearAudit.setCreateTime(new Date());
                xjsYearAudit.setUpdateTime(new Date());
                xjsYearAudit.setCreateBy("system");
                xjsYearAudit.setUpdateBy("system");
                xjsYearAuditDao.insert(xjsYearAudit);

                // 发短信:
                SYuser thisUser = userDao.selectById(xjsYearAudit.getApplyUserId());
                XjsTechSendSmaRequest sendSms = new XjsTechSendSmaRequest();
                try {
                    sendSms.setTel(AESTool.decrypt(thisUser.getPhoneNo()));
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (null != sendSms.getTel()) {
                    sendSms.setCustomerID(thisUser.getUserID());
                    sendSms.setCustomerName(thisUser.getName());
                    sendSms.setCustomerType("1");
                    sendSms.setSrvType("XJS");
                    sendSms.setMessage(SMSSender.getContent(thisUser.getName(), xjsYearAudit.getName(),xjsYearAudit.getStatus()));
                    smsSender.sendSms(sendSms);
                }

                // 更新项目最后一次年审时间
                item.setLastYearAuditTime(new Date());
                // 更新项目年审次数
                if (null == item.getYearAuditNum()) {
                    item.setYearAuditNum(1);
                } else {
                    item.setYearAuditNum(item.getYearAuditNum() + 1);
                }
                // 如果是非限制类的，就前2年审
                if (DefaultConstant.NUM_1.equals(item.getProjectClass())) {
                    // 创建年份距离当前年大于2年，则不在审核
                    if (DateUtils.isDateTwoYearsAgo(item.getCreateTime())) {
                        item.setNeedYearAudit(2);
                    }
                }
                entitymDao.updateById(item);
            }
        }

        // 3.获取满足条件的历史数据
        Page<XjsTechHisResponse> hisPage = new Page<>();
        XjsTechHisQueryRequest hisMap = new XjsTechHisQueryRequest();
        hisMap.setLastYearAuditTime(DateUtils.addYears(new Date(), -1));
        List<XjsTechHisResponse> hisList = xjsTechHisDao.selectByPage(hisPage, hisMap);
        // 复制数据插入到年审表中
        if (CollectionUtils.isNotEmpty(hisList)) {
            for (XjsTechHisResponse item : hisList) {
                // 复制数据插入到年审表中
                XjsYearAudit xjsYearAudit = new XjsYearAudit();
                BeanUtils.copyProperties(item, xjsYearAudit);

                // 历史数据
                xjsYearAudit.setOtherType(2);
                xjsYearAudit.setAuditStatus(1);
                xjsYearAudit.setStatus(80);
                xjsYearAudit.setOtherId(Long.valueOf(item.getId()));
//                xjsYearAudit.setApplyDeptId(item.getApplyDeptId());
//                xjsYearAudit.setApplyUserId(item.getApplyUserId());
//                xjsYearAudit.setApplyUserName(item.getApplyUserName());
                xjsYearAudit.setReportTime(item.getCreateTime());

                // 其他信息
                xjsYearAudit.setIsEnabled(1);
                xjsYearAudit.setCreateTime(new Date());
                xjsYearAudit.setUpdateTime(new Date());
                xjsYearAudit.setCreateBy("system");
                xjsYearAudit.setUpdateBy("system");
                xjsYearAuditDao.insert(xjsYearAudit);

                // 发短信:
                SYuser thisUser = userDao.selectById(xjsYearAudit.getApplyUserId());
                XjsTechSendSmaRequest sendSms = new XjsTechSendSmaRequest();
                try {
                    sendSms.setTel(AESTool.decrypt(thisUser.getPhoneNo()));
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (null != sendSms.getTel()) {
                    sendSms.setCustomerID(thisUser.getUserID());
                    sendSms.setCustomerName(thisUser.getName());
                    sendSms.setCustomerType("1");
                    sendSms.setSrvType("XJS");
                    sendSms.setMessage(SMSSender.getContent(thisUser.getName(), xjsYearAudit.getName(),xjsYearAudit.getStatus()));
                    smsSender.sendSms(sendSms);
                }

                // 更新项目最后一次年审时间
                item.setLastYearAuditTime(new Date());
                // 如果是非限制类的，就前2年审
                if (DefaultConstant.NUM_1.equals(item.getProjectClass())) {
                    // 创建年份距离当前年大于2年，则不在审核
                    if (DateUtils.isDateTwoYearsAgo(item.getCreateTime())) {
                        item.setNeedYearAudit(2);
                    }
                }
                xjsTechHisDao.updateById(item);
            }
        }


    }


    /**
     * 查询分析--新技术项目查询
     *
     * @param map 查询参数
     * @r Result.class
     */
    @Override
    public Result<XjsTechResponse> selectAllByPage(XjsTechQueryRequest map, RequestPojo requestPojo) {
        Result<XjsTechResponse> result = new Result<>();

        // 当前用户ID
//        String staffId = requestPojo.getSysId();
//        map.setStaffId(staffId);

        // 我的申报
//        map.setQueryType("myTech");

        Page<XjsTechResponse> page = new Page<>();
        long total = com.github.pagehelper.PageHelper.count(new ISelect() {
            @Override
            public void doSelect() {
                entitymDao.selectAllByPage(page, map);
            }
        });

        // 分页
        ParamUtil.setPage(map.getPageSize(), map.getCurrentPage(), page);
        //分页查询
        List<XjsTechResponse> list = entitymDao.selectAllByPage(page, map);

        page.setRecords(list);
        page.setTotal((int) total);
        result.setResStatus(ResStatus.STATUS_SUCCESS);
        result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
        result.setResData(page);
        return result;
    }
    @Override
    public Result<XjsTechTotal> selectAllByTotal(){
        Result<XjsTechTotal> result = new Result<>();
        //总数
        Integer total = entitymDao.selectTotal(0);
        //已完成
        Integer finish = entitymDao.selectTotal(1);
        Integer run = entitymDao.selectTotal(2);
        Integer year = entitymDao.selectTotal(3);
        Page<XjsTechTotal> page = new Page<>();
        XjsTechTotal techTotal = new XjsTechTotal();
        techTotal.setApplyTotal(total);
        techTotal.setFinishTotal(finish);
        techTotal.setRunTotal(run);
        techTotal.setYearTotal(year);
        List<XjsTechTotal> list = new ArrayList<>();
        list.add(techTotal);
        page.setRecords(list);
        result.setResData(page);
        result.setResStatus(ResStatus.STATUS_SUCCESS);
        result.setResMsg(ResStatus.STATUS_SUCCESS_MSG);
        return result;
    }

    @Override
    public Result selectProjectNumber() {
        String year = String.valueOf(LocalDate.now().getYear());
        Integer count = entitymDao.countAllTotal(year);
         Result result = new Result();
        String code  = year + String.format("%04d", count + 1);
        result.setObjData(code);
        result.setResStatus("S0000");
        final Page page = new Page();
        page.setTotal(Integer.parseInt(code));
        result.setResData(page);
        return result;
    }
}
